Los principales objetivos de este ejercicio fueron crear un scheduler que permita ir corriendo las tareas
de forma intercalada y eliminarlas de la ejecuci\'on, y actualizar las rutinas de excepciones para implementar
los servicios de \texttt{int 0x45}, los cambios de tareas, y las capturas y proceso de excepciones eliminando
tareas.

\subsubsection{Scheduler}
El archivo {\bf sched.c} implementa el scheduler. Este se basa es dos arreglos \texttt{unsigned short tareas[
CANT\_TAREAS]} y \texttt{int ciclo[CANT\_TAREAS]} que almacenan respectivamente los \'indices de la GDT de las
tareas y cu\'ales est\'an activas, y un contador \texttt{int cantTareasActuales} que ayuda a saber
cu\'antas tareas est\'an todav\'ia ejecutandose.
\\
\hspace*{10pt}
El m\'etodo \texttt{inicializar\_scheduler()} se encarga de cargar al arreglo \texttt{tareas} los \'indices de
la GDT de las 5 tareas, al arreglo \texttt{ciclo} con las 5 tareas, y marcar que las 5 tareas est\'an activas y
la pr\'oxima a ejecutarse es la primera.
\\
\hspace*{10pt}
Adem\'as, este m\'etodo tambi\'en inicializa un arreglo \texttt{int shared[CANT\_TAREAS]} que nos permite almacenar
la posici\'on de memoria compartida de cada tarea para su f\'acil acceso m\'as tarde. Para ello se utilizan los
valores del arreglo \texttt{px} del archivo {\bf rand.c}.
\\
\\
\hspace*{10pt}
Adem\'as del m\'etodo principal, nuestro scheduler cuenta tambi\'en con varios m\'etodos que nos sirven de helpers
para resolver de forma m\'as simple distintas funcionalidades del sistema.
\\
\hspace*{10pt}
El m\'etodo \texttt{proximo\_indice()} nos devuelve el \'indice en la GDT de la pr\'oxima tarea a ejecutar y avanza
autom\'aticamente la variable \texttt{actual} para estar listos para el siguiente avance. Este m\'etodo es
esencial para realizar m\'as tarde el intercambio de tareas.
\\
\hspace*{10pt}
Igual de importante es el m\'etodo \texttt{eliminar\_tarea(\_cr3)}, que nos permite quitar de la
ejecuci\'on la tarea actual. Esto se hace quitando la tarea del arreglo \texttt{ciclo}, y decrementando el contador
\texttt{cantTareasActuales}. Adem\'as, es importante desmapear las direcciones virtuales de c\'odigo y stack,
proceso realizado gracias al m\'etodo \texttt{unmapear\_pagina} implementado en el Ejercicio 4.
\\
\hspace*{10pt}
El m\'etodo \texttt{set\_page(indice, \_cr3)} nos facilita la funcionalidad de la interrupci\'on \texttt{0x45}
realizando el mapeo de la p\'agina virtual compartida a un nuevo \'indice dentro de la arena realizando una
llamada a \texttt{mapear\_pagina}. Adem\'as, actualizamos el arreglo \texttt{shared} para contar siempre con la
informaci\'on correcta a la hora de dibujar la arena en pantalla.
\\
\hspace*{10pt}
El m\'etodo \texttt{inicializar\_arena()} nos permite justamente inicializar la pantalla dibujando las posiciones
iniciales de los c\'odigos, stacks y p\'aginas compartidas de cada tarea. El m\'etodo \texttt{identificar\_tarea(\_cr3)}
es un helper que nos permite determinar cu\'al es la tarea ejecutandose actualmente. \'Este es esencial a la hora
de realizar m\'ultiples acciones sobre la tarea actual sin tener m\'as informaci\'on que el {\bf cr3} para determinar
de qu\'e tarea se trata.
\\
\hspace*{10pt}
Finalmente, los m\'etodos \texttt{posicionCodigo}, \texttt{posicionStack} y \texttt{posicionShared} nos permiten
conocer en todo momento la posici\'on dentro de la arena del c\'odigo, stack y p\'agina compartida de cada tarea,
facilitandonos su visualizaci\'on en pantalla y la resoluci\'on de la interrupci\'on \texttt{0x45}.
\\
\\
\hspace*{10pt}
Para inicializar el scheduler alcanza con realizar una llamada a \texttt{inicializar\_scheduler} desde el Kernel.
Luego, las distintas interrupciones (de reloj, por ejemplo) se encargar\'an de ir intercambiando las tareas seg\'un
corresponda.
Adem\'as realizamos desde el mismo Kernel una llamada a \texttt{inicializar\_arena} para que la pantalla est\'e
completa desde el primer momento, dado que sino reci\'en se actualizar\'ia al llegar el primer tick de reloj o
interrupci\'on, y algunas tareas terminan demasiado r\'apido como para poder apreciarlas.

\subsubsection{Arena}
Para dibujar la arena contamos con el archivo {\bf arena.asm} que pone a nuestra disposici\'on tres sets de m\'etodos.
Para el c\'odigo contamos con \texttt{dibujar\_codigo}, \texttt{pintar\_codigo}, \texttt{limpiar\_codigo} y
\texttt{borrar\_codigo}. El primero se encarga de identificar la tarea y la posici\'on en la arena de su c\'odigo,
y se los facilita a \texttt{pintar\_codigo} que se encarga efectivamente de dibujar en la pantalla el c\'odigo en
su posici\'on de la arena. Similarmente, \texttt{limpiar\_codigo} identifica la tarea y la posici\'on del c\'odigo
para que \texttt{borrar\_codigo} borre de la pantalla la posici\'on de la arena que ocupaba el c\'odigo. Esto es
utilizado, por ejemplo, cuando una tarea es eliminada.
\\
\hspace*{10pt}
El stack y la p\'agina compartida (shared) cuentan con m\'etodos an\'alogos permitiendo entre todos manejar la arena
en pantalla y representar correctamente lo que est\'a sucediendo con las tareas.

\subsubsection{Interrupci\'on \texttt{0x45}}
Para cumplir con el servicio solicitado fue necesario modificar por completo esta interrupci\'on.
Al ser llamada, eval\'ua el valor de {\bf eax} para determinar si se invoc\'o \texttt{set\_page} o \texttt{get\_code\_stack}.
De no haber sido invocada ninguna de estas dos, se procede a saltar a una nueva excepci\'on (\texttt{\_isr69Error})
por par\'ametro incorrecto, cuyo comportamiento es similar al de las otras excepciones y por lo tanto ser\'a descripto
m\'as adelante.
\\
\hspace*{10pt}
De tratarse de un \texttt{set\_page}, limpiamos la posici\'on shared de la tarea en la arena en pantalla y llamamos
al m\'etodo \texttt{setPage} del Scheduler descripto anteriormente. Luego, alcanza con actualizar la arena en pantalla
y saltar a la tarea Idle para que esta ocupe el resto del quantum actual antes de terminar.
\\
\hspace*{10pt}
De tratarse de un \texttt{get\_code\_stack}, procedemos a llamar a los m\'etodos \texttt{posicionCodigo} y
\texttt{posicionStack} del Scheduler mencionados previamente, y guardar sus resultados en {\bf ecx} y {\bf edx}
respectivamente. Alcanza entonces con retornar de la interrupci\'on para devolver los valores solicitados.

\subsubsection{Pausar y Reiniciar}
El comportamiento de pausar y reiniciar la ejecuci\'on est\'a dividido en dos partes. La primera ocurre al presionar
las teclas {\bf P} o {\bf R} y es capturada por la interrupci\'on de teclado. Al ocurrir esto, seteamos una variable
\texttt{isrPausa} en {\bf 1} (pausar) o {\bf 0} (reiniciar) para procesar efectivamente la pausa en el pr\'oximo
tick del reloj. Este procedimiento ser\'a descripto a continuaci\'on.

\subsubsection{Interrupci\'on de Reloj}
La rutina de interrupci\'on de reloj sufre varias modificaciones. La primera es, luego de actualizar el reloj general de
la aplicaci\'on, actualizar el reloj individual de cada tarea para marcar su ejecuci\'on.
\\
\hspace*{10pt}
Luego procedemos a verificar si la ejecuci\'on debe pausarse o no. Para ello leemos la variable \texttt{isrPausa}.
De ser nula, seguimos con el curso normal de la interrupci\'on. De lo contrario, debemos determinar si el sistema ya
se encontraba pausado o debe pausarse. En caso ya encontrarse pausado, simplemente informamos al PIC que ya se atendi\'o
la interrupci\'on y saltamos al final de esta.
\\
\hspace*{10pt}
De lo contrario, debemos tener cuidado ya que si la tarea actual era la Idle (por haber hecho un \texttt{set\_page} o
haber capturado una excepci\'on, por ejemplo) no podemos saltar a Idle ya que esto producir\'ia un error. Nos aprovechamos
entonces del m\'etodo \texttt{identificarTarea} del Scheduler para determinar la situaci\'on, y seg\'un ello hacemos lo
mismo que si ya estuvieramos pausados o saltamos a la tarea Idle.
\\
\hspace*{10pt}
La ejecuci\'on normal de la interrupci\'on prosigue actualizando la arena y pidiendole al Scheduler la proxima tarea con una
llamada a \texttt{proximo\_indice}. De ser este igual a 0, se produce una situaci\'on similar a la descripta reci\'en y no
debemos saltar ya que ser\'ia saltar a la misma tarea y producir un error. De lo contrario, informamos al PIC que ya se
atendi\'o la interrupci\'on y saltamos a la pr\'oxima tarea para continuar con su ejecuci\'on.

\subsubsection{Excepciones}
Las rutinas de proceso de las excepciones (\texttt{\_isr0} a \texttt{\_isr19} y la nueva \texttt{\_isr69Error}) contaban
desde el Ejercicio 2 con un comportamiento muy simple, tan solo mostrando el nombre del error y colgando el sistema.
Para adecuarse a los nuevos requerimientos, fue necesario modificar este comportamiento. Todas las interrupciones tienen
un comportamiento an\'alogo, por lo que s\'olo describiremos el comportamiento de una de ellas.
\\
\hspace*{10pt}
Al capturar una excepci\'on con una interrupci\'on, esta procede primero que nada a deshabilitar las interrupciones para
asegurarse que el procesamiento de la excepci\'on no se vea incorrectamente interrumpido. A continuaci\'on imprimimos en
pantalla los valores de los principales registros y la descripci\'on del error en cuesti\'on. Esto se realiza con una
llamada al m\'etodo \texttt{imprimir\_registros}, que se encuentra en el archivo {\bf registros.asm}.
\\
\hspace*{10pt}
Adem\'as, marcamos la tarea que gener\'o el error junto a esta descripci\'on, y copiamos tambi\'en este mensaje al \'area
destinada a cada tarea en la parte inferior de la pantalla gracias a una llamada al m\'etodo \texttt{imprimir\_tarea} del
archivo {\bf tareas.asm}.
\\
\hspace*{10pt}
Luego procedemos a eliminar la tarea del ciclo de ejecuciones actual gracias al m\'etodo \texttt{eliminar\_tarea} del
Scheduler descripto anteriormente, y borramos de la arena en pantalla el c\'odigo, stack y p\'agina compartida de la
tarea en cuesti\'on.
\\
\hspace*{10pt}
Finalmente realizamos un salto a la tarea Idle para completar el quantum asignado a la tarea que fall\'o y poder continuar
con la ejecuci\'on normal de las tareas restantes.

\subsubsection{Capturas de pantalla}
A continuaci\'on presentamos tres capturas de pantalla mostrando el sistema en pleno funcionamiento.
Para poder analizar mejor el comportamiento y crear mejores capturas, aplicamos a las tareas proporcionadas por la c\'atedra
un delay para que se disparen por separado y con un relativo tiempo entre s\'i. Esto nos permiti\'o validar que la pantalla
se est\'e actualizando correctamente y el intercambio de tareas sea el correcto.
\\
\\
\hspace*{10pt}
La primer imagen muestra la ejecuci\'on tras las fallas (esperadas) de las tareas 1 y 2. Dado que la tarea 1 fall\'o primero,
solo podemos ver el error ocurrido en su descripci\'on en la parte inferior de la pantalla. La tarea 2, por el contrario,
muestra el error tanto en la parte inferior como en el cuadro de errores de la derecha, contando con el detalle de los
registros.
Al haber fallado y sido quitadas del ciclo de ejecuci\'on, ambas tareas desaparecieron de la arena.

\begin{figure}[H]
	\centering
	\includegraphics[scale=0.5]{Images/ej7I.png}
	\centering
	\label{fig_ej7I}
\end{figure}

\hspace*{10pt}
La segunda imagen muestra la ejecuci\'on un tiempo despu\'es, con las cinco tareas ejecut\'andose y la tarea 4 habiendo fallado.
Esta reemplaz\'o a la tarea 2 en el detalle de errores y desapareci\'o de la arena. Adem\'as, como puede verse, las tareas 3
y 5 est\'an moviendo sus p\'aginas compartidas a lo largo de la arena.

\begin{figure}[H]
	\centering
	\includegraphics[scale=0.5]{Images/ej7III.png}
	\centering
	\label{fig_ej7II}
\end{figure}

\hspace*{10pt}
La tercer y \'ultima imagen muestra el sistema en su estado final. La tarea 5 pis\'o el c\'odigo de la tarea 3 y \'esta por
lo tanto fall\'o, como puede verse en el cuadro de errores o la parte inferior de la pantalla. Vemos adem\'as como s\'olo queda
la tarea 5 en la arena y su p\'agina compartida contin\'ua moviendose.

\begin{figure}[H]
	\centering
	\includegraphics[scale=0.5]{Images/ej7IV.png}
	\centering
	\label{fig_ej7IV}
\end{figure}

